#include "PlayerEntity.h"
#include "World.h"

PlayerEntity::PlayerEntity(const irr::core::string<c8>& entityModel, const irr::core::string<c8>& entitySkin, const irr::core::string<c8>& weaponModel, const irr::core::string<c8>& weaponSkin): Entity(), AnimatedEntity(entityModel, entitySkin, weaponModel, weaponSkin), LivingEntity()
{
    cam__ = 0;
    lookUp__ = 0;

    movement__ = 0.0;
    turn_angle__ = 0.0;
    turn_from_mouse__ = 0.0;

    camera_distance__ = -50.0;

    getNode()->setID(512) ;
    setType("Player");
}

PlayerEntity::~PlayerEntity()
{
	if (cam__)
	{
		cam__->remove();
		cam__ = 0;
	}

	if (lookUp__)
	{
		lookUp__->remove();
		lookUp__ = 0;
	}
}

void PlayerEntity::createCamera()
{
	lookUp__ = smgr__->addEmptySceneNode(node__);
	cam__=smgr__->addCameraSceneNode(lookUp__, vector3df(camera_distance__, 40.0, 0.0), node__->getPosition()+vector3df(0, 30, 0));

	lookUp__->setName("DummyLookupCameraNode");
	lookUp__->setID(5);
	cam__->setName("PlayerCameraNode");
	cam__->setID(5);
	getNode()->setName("PlayerNode");
}

void PlayerEntity::set3rdPersonView()
{
	if (!cam__)
		createCamera();
	smgr__->setActiveCamera(cam__);
}

bool PlayerEntity::isCameraActive()
{
	return cam__ == smgr__->getActiveCamera();
}

bool PlayerEntity::attack()
{
				
     if(timeCounter__ >= 0.5f)
     {
         setAnimation(EMAT_STAND,true) ;
    
    	irr::core::string<c8> plop = getType() ; 
    
    	int lastID = node__->getID();
    	node__->setID(5);
    
    	SMaterial sm;
    	sm.setFlag(EMF_LIGHTING, false);
    	sm.AmbientColor.color = 0xFFFF00FF;
    	sm.DiffuseColor.color = 0xFFFF00FF;
    	sm.EmissiveColor.color = 0xFFFF00FF;
    
    
    	Map* m = World::getMap();
        bool test=false;
        ISceneNode* node=getNode();
        vector3df start = node->getPosition();
    	vector3df end = vector3df(600, 0, 0);
    	end.rotateXZBy(-node->getRotation().Y, vector3df(0, 0, 0));
    
    
    	Entity * target = m->RayCastForEntity(node,start,end) ;
    	end.rotateXZBy(-20,vector3df(0, 0, 0));
	    Entity* target2=World::getMap()->RayCastForEntity(node,start,end);

        end.rotateXZBy(40,vector3df(0, 0, 0));
	    Entity* target3=World::getMap()->RayCastForEntity(node,start,end);
	    if(target)
	    {
            test=true;
         }       
          else if(target2)
          {
                     test=true;
                     target=target2;
          }   
          else if(target3)
          {
                     test=true;
                     target=target3;
          }
   
    	if((test) && (dynamic_cast<LivingEntity*>(target)) && (target->getNode()->getBoundingBox().getExtent().getLength()))
    	{
    		if(dynamic_cast<LivingEntity*>(target))
    		{
    			dynamic_cast<LivingEntity*>(target)->removeLife(15) ;
    			sendMessage(target,"Attack") ;
    			setAnimation(EMAT_ATTACK,false) ;

			// sending messages to all allies			
			sendMessage(std::string("PlayerAllied"),std::string("Under_Attack"),target->getType().c_str(),target->getNode()->getPosition()); 
    			
    		}
    
    	}
    
    	if (debug[Debug::VISION_CONE])
    	{
    		matrix4 mat;
    		matrix4 bak = World::getVideoDriver()->getTransform(ETS_WORLD);
    		World::getVideoDriver()->setTransform(ETS_WORLD, mat); 
    		World::getVideoDriver()->setMaterial(sm);
    		World::getVideoDriver()->draw3DLine(getNode()->getPosition(), getNode()->getPosition() + end, SColor(255, 255, 0, 255));
    		World::getVideoDriver()->setTransform(ETS_WORLD, bak);
    	}
    
    	node__->setID(lastID);
        timeCounter__ = 0 ;
    	return true ;
     }

	return false ;
}

void PlayerEntity::update()
{
	World* w = World::getWorld();
	if(isDead())
	{
		
		s32 debut, fin, fps;
		IAnimatedMeshMD2* md = dynamic_cast<IAnimatedMeshMD2*>(this->getEntityMesh());
		//md->getFrameLoop("crdeath",debut,fin,fps);
		md->getFrameLoop(EMAT_DEATH_FALLBACK,debut,fin,fps);
		setAnimation(debut,fin-3, false);
		return;
	}

//	std::cout << "player at " << getNode()->getPosition().X << " " << getNode()->getPosition().Y << " " << std::endl ;
	// set Orientation
	double r = turn_angle__ * attributes__["rotatespeed"] * w->elapsedTime();
	r += turn_from_mouse__;

	node__->setRotation(node__->getRotation() + vector3df(0.0, r, 0.0));
	// set Position
	vector3df direction(0.0, 0.0, 0.0);
	vector3df origin(0.0, 0.0, 0.0);

	direction.X = movement__;
	direction.rotateXZBy(node__->getRotation().Y, origin);
	direction.normalize();
	direction *= attributes__["speed"] * w->elapsedTime();
	direction.Z = -direction.Z;
	node__->setPosition(node__->getPosition() + direction);

	// update animation
	if (movement__ != 0.0)
		setAnimation("run");
	else
		setAnimation("stand");
		
	// update the time counter for attacking	
    timeCounter__ += World::getWorld()->elapsedTime() ;
	// update camera:
	cam__->setTarget(node__->getPosition() + vector3df(0, 40, 0));

	// due to the nature of events, must set turn_from_mouse__ to 0
	// or the player will continue to turn if RMB is pressed
	// and no motion is detected
	turn_from_mouse__ = 0.0;
	
	// read messages
	Message m = readMessage() ; 
}
               

